package com.gaojinqi.base.common.service.imp;

import com.gaojinqi.base.common.constant.RespConst;
import com.gaojinqi.base.common.exception.BizRuntimeException;
import com.gaojinqi.base.common.model.BaseEntity;
import com.gaojinqi.base.common.model.PageReq;
import com.gaojinqi.base.common.model.PageResp;
import com.gaojinqi.base.common.service.BaseService;
import com.gaojinqi.base.common.util.PageUtil;
import com.gaojinqi.base.core.jpa.BaseRepository;
import com.gaojinqi.base.core.jpa.util.AnnotationQueryUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.List;

/**
 * 通用service接口实现类
 *
 * @author gao.jinqi
 * @date 2020-03-21 23:38
 */
public class BaseServiceImpl<T, ID extends Serializable> implements BaseService<T, ID> {

    @Autowired
    protected BaseRepository<T, ID> baseRepository;

    public BaseServiceImpl() {
    }

    @Override
    @Transactional
    public void save(T entity) {
        this.baseRepository.saveOneSelective(entity);
    }

    @Override
    @Transactional
    public void update(T entity) {
        this.baseRepository.updateOneSelective(entity);
    }

    @Override
    public PageResp<T> page(Object entity) {
        PageReq request = new PageReq();
        return this.page(entity, request);
    }

    @Override
    @Transactional
    public void deleteById(ID id) {
        if (id == null) {
            throw new BizRuntimeException(RespConst.RespEnum.ILLEGAL);
        } else {
            this.baseRepository.deleteById(id);
        }
    }

    @Override
    @Transactional
    public void deleteByIds(List<ID> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new BizRuntimeException(RespConst.RespEnum.ILLEGAL);
        } else {
            for (ID id : ids) {
                this.baseRepository.deleteById(id);
            }
        }
    }

    @Override
    public PageResp<T> page( Object entity, PageReq pageReq, Sort.Order... order) {
        if (StringUtils.isEmpty(pageReq)) {
            pageReq = new PageReq();
        }
        // 如果是BaseEntity的子类，并且没有设置排序字段，则默认使用BaseEntity#DEFAULT_SORT_BY
        if (entity instanceof BaseEntity && StringUtils.isEmpty(pageReq.getSortBy())) {
            pageReq.setSortBy(BaseEntity.DEFAULT_SORT_BY);
        }
        Pageable pageable;
        if (entity == null) {
            pageable = PageUtil.getPageable(pageReq);
            return PageUtil.getPageResponse(this.baseRepository.findAll(pageable));
        } else {
            /*ExampleMatcher matcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
            Example<T> example = Example.of(entity, matcher);*/
            Specification<T> specification = AnnotationQueryUtil.getSpecification(entity);
            Sort sort;
            if (order != null && order.length > 0) {
                sort = Sort.by(order);
                pageable = PageRequest.of(pageReq.getPage() - 1, pageReq.getSize(), sort);
            } else {
                pageable = PageUtil.getPageable(pageReq);
            }
            return PageUtil.getPageResponse(this.baseRepository.findAll(specification, pageable));
        }
    }

    @Override
    public T findById(ID id) {
        if (id == null) {
            throw new BizRuntimeException(RespConst.RespEnum.ILLEGAL);
        } else {
            return this.baseRepository.findById(id)
                    .orElseThrow(() -> new BizRuntimeException(RespConst.RespEnum.NULL));
        }
    }

}